# Mirth

A minimalistic interpreter for a Joy-like esoteric language.

## Running

If you have a `make` installed, simply type `make` to build the
executable.  Otherwise you can run the `./build` script.  Then run
`./mirth`.

## Programming in Mirth

Mirth programs consist of a sequences of ASCII characters and `[`- and
`]`-quoted sequences of characters (aka. "quotes").

Mirth passes intermediate computations on an implicit "data stack",
much like Joy, Forth, and other stack-based languages.  Operations may
push values to the stack, pop values from the stack, reorder stack
items, or a combination of the above.

Alphabetic characters in a program cause the ASCII codepoint of that
character to be pushed to the top of the stack.

Digit characters in a program are recognized as such and cause the
corresponding digit to be pushed to the data stack.  Consecutive
digits are treated as separate numbers.  E.g. the input `123` causes
first the number 1 to be pushed onto the stack, followed by the number
2, then the number 3.

Most of the ASCII symbol characters are "primitive" operators that
perform some action, perhaps consuming values from or producing values
on the stack.  Some of these operators are overloaded: the specific
action they perform depends on whether the stack items they operate on
are integers or quotes.

Whitespace is insignificant and ignored in Mirth programs.

### Stack operators

  The value at the Top Of the Stack is referred to as "TOS", and
the value Second On the Stack is referred to as "SOS".

* `$` duplicates the TOS ("dup")
* `>` duplicates the SOS and pushes it on top ("over")
* `%` discards the TOS ("drop"/"pop")
* `\` swaps the TOS and SOS ("swap")
* `(` pushes a quoted copy of the contents of the data stack. ("stack")
* `)` replaces the stack with the contents of the quoted TOS ("unstack")
* `@` reorders stack values according to quoted indices at TOS ("shuffle")

E.g.

```
13$
=> 1 3 3
13>
=> 1 3 1
13%
=> 1
13\
=> 3 1
13(
=> 1 3 [3 1]
hello[[world]])
=> [world]
helo[32110]@
=> o l l e h
```

The `@` operator possibly needs some more explaining.  It expects a
quote at TOS that contains zero-based character indices, where the
index 0 refers to the top of the stack and indices increase as you
head towards the bottom of the stack.  The maximum index indicates the
extent of the shuffle operation, or how many stack items are dropped
from the stack.  Those stack items are replaced with the indexed stack
items given in the list, where the front of the list becomes the TOS.
E.g. the classic "rot" operation from Forth could be expressed as
`[201]@`, and `$` is equivalent to `[00]@`.  The "nip" operation from
Forth could be expressed as `[20]@` assuming there is a stack item at
index 2 to work with, but it could be better expressed as `\%`.

### Arithmetic

Multi-digit integers must be formed on the stack using the primitive
arithmetic primitives `+`, `-`, `*`, and `/` applied to two integers.
E.g.

```
48*
=> 32
25*
=> 10
19+
=> 10
1356*$**+
=> 2701
```

Since there are many ways in which a single number can be represented
in this way, Mirth encourages the programmer to express their own
numeric individuality.

Note, however, that alphabetic character input causes the ASCII
codepoint of that character to be pushed to the stack, so one could
use those for inputing larger numbers if desired.  E.g. `d` leaves 100
on top of the stack, which may be more intuitive than `455**`,
depending on how comfortable you are with ASCII codepoints.

### Logic and Control Operators

In Mirth `true` is represented as the integer `-1`, and `false` as `0`.

* `<` pops TOS and SOS, pushes `-1` if SOS is less than TOS, otherwise `0`
* `=` pops TOS and SOS, pushes `-1` if SOS is equal to TOS, otherwise `0`
* `~` pops TOS, pushes the binary complement of TOS
* `` ` `` pushes `-1` if TOS is a quote ("quote?")

### Quote manipulation

Some of the arithmetic and logic operators' behavior is overloaded
when one of the operands is a quote:

* `+` conses SOS onto the front of TOS, if TOS is a quote ("cons")
* `-` pops TOS, pushes the first element of TOS, then the rest, if TOS is a quote ("uncons")
* `*` concatenates SOS and TOS, if TOS is a quote, assuming SOS is a quote ("concat")
* `|` pops TOS, pushes the reverse of TOS, if TOS is a quote ("reverse")

E.g.

```
h[ello]+
=>[hello]
[135][246]+
=>[[135]246]
[135]--
=>1 3 [5]
[0]-3\+
=>0 [3]
[hello][, world!]*
=>[hello, world!]
[12345]|
=>[54321]
```

The following operators provide for treating quotes as programs, they
"execute" a quote from the stack in some way.  A quote is executed by
walking its contents from head to tail and executing each element in
turn.

* `!` executes the TOS quote ("do")
* `_` executes the TOS quote underneath SOS, i.e. SOS is temporarily
  removed from the stack and returned after TOS is finished executing
  ("dip")
* `?` execute TOS quote if SOS is non-zero ("do-if")

E.g.

```
2[1+]!
=> 3
27[1+]_
=> 3 7
2[1+]$_!
=> 4
00=[7]?
=> 7
```

### Input and Output

* `,` prints a quote as a flat sequence of characters, or prints the
  single character at TOS.
* `.` prints TOS as a signed integer.
* `^` pushes a single character read from standard input to the stack

E.g.

```
hello,,,,,
=|olleh
[hello, world!],
=|hello, world!
[digit: ],^68*-.
=|digit: 3
[Y/n: ],^19+,Y=[[yes, of course],19+,]?
=|Y/n: Y
=|yes,of course
=|
```

Recall from the "Arithmetic" section that multi-digit integers cannot
be formed on the stack without performing arithmetic.  However,
"integers" can be printed using a quote without limitation, of course,
since they're just interpreted as characters:

```
[2049],
=|2049
```

### Variables

There are 128 integer-indexed variables that may be used by Mirth
programs.

* `:` Set variable TOS (an integer in [0,127]) to SOS.  Discard both
  from the stack. ("define")
* `;` Replace variable index at TOS with that variable's value. ("value")

E.g.

```
37*f: 89+b: f;b;* 9b;+
=> 357 26
[[hello],48*,]g: g;!g;!g;! [!!!],
=|hello hello hello !!!
```

It may happen that `:` encounters a quote at TOS.  If this is the case
then it expects TOS to contain a single alphabetic character C
(i.e. in the set [a-zA-Z]) and expects SOS to also be a quote.  It
then creates an "immediate" operator.  If C is later encountered, its
quote is immediately executed, without needing to fetch and execute
(`;!`).  This allows one to define and use primitive-like operators
more concisely.

E.g.
```
[1+][i]:
[2*][d]:
0i 0ii 0iii 9iiii $d
=> 1 2 3 13 26
```

or to write self-documenting programs:
```
[[25*,]][h]:
[1.][n]:  [2.][t]:  [[red],][r]:  [[blue],][b]:
[]$$$$$$$$ [o]:[e]:[w]:[d]:[l]:[u]:[f]:[i]:[s]:

one fish!  two fish!  red fish!  blue fish!
=|1
2
red
blue
```

or to program in your preferred style while maintaining a formal
outward interface:
```
[[25*,]]$[i]:[e]:  [48*,][a]:
[[Name:],][z]:  [%%%%0[]][m]:  [%%][x]:
[^$ 19+=~[\+l]?][l]: [[]l%|][k]:
[[Hi],a][b]: [,[!],][y]:

hai!  I can haz ur nam?  kthxbye!
```

## Limitations and Future Work

* Currently Mirth has no garbage collection.  Long running programs
  that use a lot of quotes and quote-manipulating operators may
  exhaust Mirth's fixed-size cons-pool.

Mirth may have bugs.  If you encounter any, please email the author.

---
Author: Eric Bavier <bavier@member.fsf.org>

License: GPL3+
